/**
 * @file    drv_i2c.c
 * @brief   i2c驱动
 * @author  Liu wei
 * @version 1.0.1
 * @date    2023-04-18
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-04-18 <td>1.0.1     <td>Liuwei   <td>首次创建
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "drv_i2c_soft.h"
#include "cfg_prj.h"
/* macro/define --------------------------------------------------------------*/
#define I2C_DELAY    (4)
/* typedef -------------------------------------------------------------------*/

/* local functions -----------------------------------------------------------*/

/* static variables ----------------------------------------------------------*/
static const i2c_port_type i2c_port_obj[DRV_I2C_MAX] = 
{

	{RTC_SCL_PORT , RTC_SCL_PIN , RTC_SDA_PORT , RTC_SDA_PIN}, 
    {EEP_SCL_PORT , EEP_SCL_PIN , EEP_SDA_PORT , EEP_SDA_PIN},  
};

/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
/**
 * @brief  初始化i2C模块
 * @param  i2c_id : i2c ID
 */
void drv_i2c_soft_init(uint8_t i2c_id)
{
	if(i2c_id >= DRV_I2C_MAX)
		return ;
	
    i2c_cfg_scl_out(i2c_port_obj[i2c_id]);

    i2c_cfg_sda_out(i2c_port_obj[i2c_id]);
	
	drv_i2c_release(i2c_id);
}

/**
 * @brief  释放I2C信号
 * @param  i2c_id : i2c ID
 */
void drv_i2c_release(uint8_t i2c_id)
{
	if(i2c_id >= DRV_I2C_MAX)
		return ;
	
    i2c_set_sda(i2c_port_obj[i2c_id]);

    i2c_set_scl(i2c_port_obj[i2c_id]);
}

/**
 * @brief  I2C start信号
 * @param  i2c_id : i2c ID
 */
void drv_i2c_soft_start(uint8_t i2c_id) 
{
	if(i2c_id >= DRV_I2C_MAX)
		return ;
	
  	i2c_cfg_sda_out(i2c_port_obj[i2c_id]);
    i2c_set_scl(i2c_port_obj[i2c_id]);
    i2c_delay_us(I2C_DELAY);
	i2c_set_sda(i2c_port_obj[i2c_id]);
	i2c_delay_us(2 * I2C_DELAY);
	
    i2c_clr_sda(i2c_port_obj[i2c_id]);
    i2c_delay_us(I2C_DELAY);
    i2c_clr_scl(i2c_port_obj[i2c_id]);
    i2c_delay_us(I2C_DELAY);
}

/**
 * @brief  I2C 停止信号
 * @param  i2c_id : i2c ID
 */
void drv_i2c_soft_stop(uint8_t i2c_id) 
{
	if(i2c_id >= DRV_I2C_MAX)
		return ;
	
	i2c_cfg_sda_out(i2c_port_obj[i2c_id]);
	i2c_clr_scl(i2c_port_obj[i2c_id]);
	i2c_delay_us(I2C_DELAY);
    i2c_clr_sda(i2c_port_obj[i2c_id]);
	i2c_delay_us(I2C_DELAY);
	
    i2c_set_scl(i2c_port_obj[i2c_id]);
    i2c_delay_us(I2C_DELAY);
    i2c_set_sda(i2c_port_obj[i2c_id]);
    i2c_delay_us(I2C_DELAY);
}

/**
 * @brief  I2C 发送一个字节数据
 * @param  byte
 */
void drv_i2c_soft_write_byte(uint8_t i2c_id , uint8_t byte) 
{
    uint8_t i = 0;
	
	if(i2c_id >= DRV_I2C_MAX)
		return ;
	
	i2c_cfg_sda_out(i2c_port_obj[i2c_id]);
    
    for (i = 0; i < 8; i++) 
    {
		i2c_delay_us(I2C_DELAY);
        if (byte & 0x80) 
        {
            i2c_set_sda(i2c_port_obj[i2c_id]);
        } else 
        {
            i2c_clr_sda(i2c_port_obj[i2c_id]);
        }
        i2c_delay_us(I2C_DELAY);
        i2c_set_scl(i2c_port_obj[i2c_id]);
        i2c_delay_us(I2C_DELAY);
        i2c_clr_scl(i2c_port_obj[i2c_id]);
        byte <<= 1; 
    }
}

/**
 * @brief  I2C 读取一个字节数据
 * @return uint8_t : 读取数据
 */
uint8_t drv_i2c_soft_read_byte(uint8_t i2c_id) 
{
    uint8_t i = 0;
    uint8_t byte = 0;
	
	if(i2c_id >= DRV_I2C_MAX)
		return FALSE;
	
	i2c_cfg_sda_in(i2c_port_obj[i2c_id]);
    for (i = 0; i < 8; i++) 
    {
		i2c_clr_scl(i2c_port_obj[i2c_id]);
		i2c_delay_us(I2C_DELAY);
		i2c_set_scl(i2c_port_obj[i2c_id]);
		i2c_delay_us(I2C_DELAY);
        byte <<= 1;
        if (i2c_read_sda(i2c_port_obj[i2c_id])) 
        { 
            byte |= 0x01; 
        }
        i2c_delay_us(I2C_DELAY);
    }
    return byte;
}

/**
 * @brief  读取ACK信号
 * @return TRUE : 成功  FALSE : 失败 
 */
uint8_t drv_i2c_soft_read_ack(uint8_t i2c_id) 
{
    uint8_t ret = TRUE;
	uint16_t error_timeout = 0;
	if(i2c_id >= DRV_I2C_MAX)
		return FALSE;
	
	i2c_cfg_sda_in(i2c_port_obj[i2c_id]);
    i2c_delay_us(I2C_DELAY);
    i2c_set_scl(i2c_port_obj[i2c_id]); 
    i2c_delay_us(I2C_DELAY);
	
	while(i2c_read_sda(i2c_port_obj[i2c_id]))
	{
		++ error_timeout;
		if(error_timeout > 255)
		{
			drv_i2c_soft_stop(i2c_id);
			return FALSE;
		}
	}
    i2c_clr_scl(i2c_port_obj[i2c_id]);
    return ret;
}

/**
 * @brief  发送ack信号
 * @param  i2c_id
 */
void drv_i2c_soft_write_ack(uint8_t i2c_id) 
{
	i2c_clr_scl(i2c_port_obj[i2c_id]);
	i2c_cfg_sda_out(i2c_port_obj[i2c_id]);
    i2c_clr_sda(i2c_port_obj[i2c_id]); 
    i2c_delay_us(I2C_DELAY);
	
    i2c_set_scl(i2c_port_obj[i2c_id]); 
    i2c_delay_us(I2C_DELAY);
    i2c_clr_scl(i2c_port_obj[i2c_id]);
    i2c_delay_us(I2C_DELAY);
}

/**
 * @brief  i2C 发送NACK信号
 * @param  i2c_id
 */
void drv_i2c_soft_write_nack(uint8_t i2c_id) 
{
	i2c_clr_scl(i2c_port_obj[i2c_id]);
	i2c_cfg_sda_out(i2c_port_obj[i2c_id]);
    i2c_set_sda(i2c_port_obj[i2c_id]); 
    i2c_delay_us(I2C_DELAY);
	
    i2c_set_scl(i2c_port_obj[i2c_id]); 
    i2c_delay_us(I2C_DELAY);
    i2c_clr_scl(i2c_port_obj[i2c_id]);
    i2c_delay_us(I2C_DELAY);
}

/**
 * @brief  检测设备是否存在
 * @param  i2c_id : i2c 地址
 * @param  dev_addr : 设备ID
 * @return uint8_t ：TRUE : 在  FALSE : 不在
 */
uint8_t drv_i2c_soft_check_device(uint8_t i2c_id, uint8_t dev_addr) 
{
    uint8_t ack_sign = 0;

    drv_i2c_soft_start(i2c_id);

    drv_i2c_soft_write_byte(i2c_id , dev_addr | DEV_I2C_RD);
    ack_sign = drv_i2c_soft_read_ack(i2c_id); /* 检测设备的ACK应答 */

    drv_i2c_soft_stop(i2c_id); /* 发送停止信号 */

    return ack_sign;
}

/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
 
/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/
